import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Stroke;
import java.awt.event.KeyEvent;
import java.awt.geom.Line2D;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.net.URLConnection;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Map;

import org.rsbot.bot.Bot;
import org.rsbot.bot.input.Mouse;
import org.rsbot.event.events.ServerMessageEvent;
import org.rsbot.event.listeners.PaintListener;
import org.rsbot.event.listeners.ServerMessageListener;
import org.rsbot.script.Calculations;
import org.rsbot.script.Constants;
import org.rsbot.script.GEItemInfo;
import org.rsbot.script.Methods;
import org.rsbot.script.Script;
import org.rsbot.script.ScriptManifest;
import org.rsbot.script.wrappers.RSInterface;
import org.rsbot.script.wrappers.RSInterfaceChild;
import org.rsbot.script.wrappers.RSNPC;
import org.rsbot.script.wrappers.RSObject;
import org.rsbot.script.wrappers.RSTile;

@ScriptManifest(authors = { "Aman" }, category = "Runecraft", name = "MGNats", version = 1.0)
public class MGNats extends Script implements ServerMessageListener,
		PaintListener {
	public double updatedVersion;
	public final double currentVersion = getClass().getAnnotation(
			ScriptManifest.class).version();

	private final AStarGC pathFinder = new AStarGC();

	public enum Action {
		BANK, GRAAHK, WALK, ENTER, CRAFT, RING, FILL, WITHDRAW_RING, SUMMON
	}

	RSTile ruinTile = new RSTile(2867, 3020);
	RSTile teleportTile = new RSTile(2786, 3006);

	protected int getMouseSpeed() {
		return mouseSpeed;
	}

	// GUI
	private graahkcraftgui gui;
	public boolean normalPath;

	public int sleepTime;
	public int mouseSpeed;
	public boolean startScript = false;
	public boolean usePouches = false;
	public boolean rest = true;

	public boolean checkspouch = false;
	public boolean checkmpouch = false;
	public boolean checklpouch = false;
	public boolean checkgpouch = false;
	// IDs
	public final static int bankChestID = 4483;

	// goal point
	Point dest;

	public final static int natID = 561;
	public final static int pessID = 7936;
	public final static int altarID = 2486;
	public final static int ruinsID = 2460;
	RSTile altarTile = new RSTile(2400, 4841);

	// pouches
	public boolean emptiedPouches = false;
	public boolean fillPouches = false;
	public boolean filledPouches = false;

	public final static int smallpouch = 5509;
	public final static int mediumpouch = 5510;
	public final static int mediumpouchdecay = 5511;
	public final static int largepouch = 5512;
	public final static int largepouchdecay = 5513;
	public final static int giantpouch = 5514;
	public final static int giantpouchdecay = 5515;

	// equipment checks
	public boolean ringDisappeared = false;
	public boolean graahkDisappeared = false;
	public boolean graahkAlreadySummoned;
	// failsafe
	public int failcount;

	// paint

	long scriptStartTime;
	public int startXP;
	public long startTime;
	public int natPrice;
	public int pessPrice;
	public long time;
	public int SHOWPAINT = 1;
	public int naturerunecount;

	Thread Antiban = new antiban();

	public boolean onStart(Map<String, String> args) {
		try {
			URLConnection url = null;
			BufferedReader in = null;
			url = new URL(
					"http://rsbotaman.webs.com/scripts/graahkcraftv2VERSION.txt")
					.openConnection();
			in = new BufferedReader(new InputStreamReader((InputStream) url
					.getContent()));
			updatedVersion = Double.parseDouble(in.readLine());
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		if (!isLoggedIn()) {
			log("Please log in before starting.");
			return false;
		} else {
			startXP = skills.getCurrentSkillExp(STAT_RUNECRAFTING);
			startTime = System.currentTimeMillis() - 1000;
			GEItemInfo natMarketPrice = grandExchange.loadItemInfo(natID);
			GEItemInfo pessMarketPrice = grandExchange.loadItemInfo(pessID);
			natPrice = natMarketPrice.getMarketPrice();
			pessPrice = pessMarketPrice.getMarketPrice();
			gui = new graahkcraftgui();
			gui.setVisible(true);
			while (!startScript) {
				wait(10);
			}
			if (startScript)
				return true;
		}
		return false;
	}

	public int loop() {
		try {
			final Action action = getAction();
			log("Current action: " + getAction());
			if (action != null) {
				switch (action) {
				case BANK:
					RSObject chest = getNearestObjectByID(bankChestID);
					RSTile chestTile = chest.getLocation();
					if (tileOnScreen(chestTile)) {
						if (!RSInterface.getInterface(INTERFACE_BANK).isValid()) {
							RSObject bankChest = getNearestObjectByID(bankChestID);
							if (bankChest != null)
								atObject(bankChest, "Use");
							wait(sleepTime());
							while (getMyPlayer().isMoving()
									|| getMyPlayer().getAnimation() != -1) {
								wait(sleepTime());
								Antiban.run();
							}
						} else {
							log("Depositing and withdrawing");
							bank.depositAllExcept(pessID, smallpouch,
									mediumpouch, mediumpouchdecay, largepouch,
									largepouchdecay, giantpouch,
									giantpouchdecay);
							log("Withdrawing ess. Ess count "
									+ getInventoryCount(pessID));
							withdraw(pessID, "Pure Essence", true);
							// bank.withdraw(pessID, 28);
							log("Ess count " + getInventoryCount(pessID));
							if (usePouches && !filledPouches
									&& getInventoryCount(pessID) >= 14) {
								log("Fill pouches.");
								fillPouches = true;
							}
							break;
						}
					} else {
						walkTo(chestTile);
						while (getMyPlayer().isMoving()) {
							wait(sleepTime());
							Antiban.run();
						}
						break;
					}
				case WITHDRAW_RING:
					RSObject chest2 = getNearestObjectByID(bankChestID);
					RSTile chestTile2 = chest2.getLocation();
					TOP: if (inventoryContains(2552)) {
						if (bank.isOpen())
							bank.close();
						leftClickInventoryItem(2552);
						ringDisappeared = false;
						break;
					} else {
						if (bank.isOpen() && ringDisappeared) {
							log("Withdrawing a new ring.");
							bank.depositAllExcept(smallpouch, mediumpouch,
									mediumpouchdecay, largepouch,
									largepouchdecay, giantpouch,
									giantpouchdecay);
							withdraw(2552, "Ring of duelling", false);
							wait(sleepTime());
							break TOP;
						} else {
							if (tileOnScreen(chestTile2)) {
								if (chest2 != null)
									atObject(chest2, "Use");
							} else
								walkTo(chestTile2);

							break;
						}
					}
					break;
				case SUMMON:
					if (getNearestObjectByID(bankChestID) == null) {
						break;
					}
					log("Inventory contains ? " + inventoryContains(12810));
					RSObject chest3 = getNearestObjectByID(bankChestID);
					RSTile chestTile3 = chest3.getLocation();
					TOP: if (inventoryContains(12810) == true) {
						log("inside");
						if (bank.isOpen())
							bank.close();
						if (skills.getCurrentSkillLevel(STAT_SUMMONING) > 15) {
							log("no need to recharge");
							if (distanceTo(chestTile3) > 10) {
								walkTo(chestTile3);
							} else {
								atInventoryItem(12810, "Summon");
								if (graahkAlreadySummoned) {
									log("Waiting for current Graahk to disappear.");
									wait(60000);
									break TOP;
								} else
									graahkDisappeared = false;
							}
						} else {
							log("recharing");
							RSObject obelisk = getNearestObjectByID(29954);
							if (tileOnScreen(obelisk.getLocation())) {
								atObject(obelisk, "Renew-points");
								while (getMyPlayer().getAnimation() != -1) {
									wait(sleepTime());
									Antiban.run();
								}
								break TOP;
							} else
								walkTo(obelisk.getLocation());
						}
					} else {
						if (bank.isOpen()) {
							bank.depositAllExcept(smallpouch, mediumpouch,
									mediumpouchdecay, largepouch,
									largepouchdecay, giantpouch,
									giantpouchdecay);
							withdraw(12810, "Spirit Graahk Pouch", false);
							wait(sleepTime());
							break TOP;
						} else {
							if (tileOnScreen(chestTile3)) {
								if (chest3 != null)
									atObject(chest3, "Use");
							} else
								walkTo(chestTile3);

							break TOP;
						}
					}
					break;
				case FILL:
					if (bank.isOpen()) {
						bank.close();
					}
					if (checkspouch)
						pouchFill(smallpouch);
					if (checkmpouch) {
						if (inventoryContains(mediumpouch))
							pouchFill(mediumpouch);
						else
							pouchFill(mediumpouchdecay);
					}
					if (checklpouch) {
						if (inventoryContains(largepouch))
							pouchFill(largepouch);
						else
							pouchFill(largepouchdecay);
					}
					if (checkgpouch) {
						if (inventoryContains(giantpouch))
							pouchFill(giantpouch);
						else
							pouchFill(giantpouchdecay);
					}
					filledPouches = true;
					fillPouches = false;
					break;
				case GRAAHK:
					if (bank.isOpen())
						bank.close();
					RSNPC graahk = getNearestNPCByID(7363);
					setCameraAltitude(true);
					atNPC(graahk, "Interact");
					wait(sleepTime());
					while (getMyPlayer().isMoving()
							|| getMyPlayer().getAnimation() != -1) {
						wait(sleepTime() + 400);
						Antiban.run();
					}
					wait(500);
					if (RSInterface.getInterface(228).isValid()) {
						clickMouse(random(140, 370), random(424, 440), true);
						wait(sleepTime());
						while (getMyPlayer().isMoving()
								|| getMyPlayer().getAnimation() != -1) {
							wait(sleepTime());
							Antiban.run();
						}
						while (!tileOnMap(teleportTile)) {
							int counter = 0;
							if (counter > 6000) {
								break;
							}
							wait(1);
							counter++;
						}
						break;
					} else {
						RSTile tile = getRandomTileInArea(2455, 3094, 2440,
								3082);
						Point p = tileToMinimap(tile);
						clickMouse(p, false);
						Antiban.run();
						break;
					}
				case WALK:
					if (getNearestObjectByID(ruinsID) == null) {
						if (normalPath) {
							if (getMyPlayer().getLocation().getX() < 2827) {
								walkTo(new RSTile(2830, 3010));
								break;
							} else if (getMyPlayer().getLocation().getX() < 2840
									&& getMyPlayer().getLocation().getX() >= 2827) {
								walkTo(new RSTile(2840, 3027));
								break;
							} else if (getMyPlayer().getLocation().getX() < 2854
									&& getMyPlayer().getLocation().getX() >= 2840) {
								walkTo(new RSTile(2860, 3028));
								break;
							} else if (getMyPlayer().getLocation().getX() >= 2854) {
								walkTo(ruinTile);
								break;
							}
						} else
							walkTo(ruinTile);
					}
				case ENTER:
					RSObject ruins = getNearestObjectByID(ruinsID);
					RSTile ruinsTile = ruins.getLocation();
					if (tileOnScreen(ruinsTile)) {
						atObject(ruins, "Enter");
						wait(sleepTime());
						while (getMyPlayer().isMoving()
								|| getMyPlayer().getAnimation() != -1) {
							wait(sleepTime());
							Antiban.run();
						}
						break;
					} else {
						if (normalPath) {
							if (getMyPlayer().getLocation().getX() < 2827) {
								walkTo(new RSTile(2830, 3010));
								break;
							} else if (getMyPlayer().getLocation().getX() < 2840
									&& getMyPlayer().getLocation().getX() >= 2827) {
								walkTo(new RSTile(2840, 3027));
								break;
							} else if (getMyPlayer().getLocation().getX() < 2854
									&& getMyPlayer().getLocation().getX() >= 2840) {
								walkTo(new RSTile(2860, 3028));
								break;
							} else if (getMyPlayer().getLocation().getX() >= 2854) {
								walkTo(ruinTile);
								break;
							}
						} else
							walkTo(ruinsTile);
					}
				case CRAFT:
					filledPouches = false;
					RSObject altar = getNearestObjectByID(altarID);
					RSTile altarTile = altar.getLocation();
					if (tileOnScreen(altarTile)) {
						while (inventoryContains(pessID)
								&& getMyPlayer().getAnimation() != 791) {
							atObject(altar, "Craft");
							wait(sleepTime() + 1000);
						}
						while (getMyPlayer().isMoving()
								|| getMyPlayer().getAnimation() != -1) {
							wait(sleepTime());
							Antiban.run();
						}
						wait(sleepTime());
						while (getMyPlayer().isMoving()
								|| getMyPlayer().getAnimation() != -1) {
							wait(sleepTime());
							Antiban.run();
						}
						while (usePouches && !emptiedPouches)
							emptyPouches();
						break;
					} else {
						walkTo(altarTile);
						break;
					}
				case RING:
					naturerunecount += getInventoryCount(natID);
					emptiedPouches = false;
					openTab(TAB_EQUIPMENT);
					clickMouse(random(683, 714), random(369, 400), false);
					atMenu("Castlewars");
					wait(sleepTime() + 1000);
					while (getMyPlayer().getAnimation() != -1) {
						wait(sleepTime());
						Antiban.run();
					}
					break;
				}
			}
		} catch (Exception e) {
		}
		return random(80, 100);
	}

	public void serverMessageRecieved(ServerMessageEvent e) {
		String message = e.getMessage();
		if (message.contains("Your ring of duelling crumbles to dust.")) {
			ringDisappeared = true;
		} else if (message
				.contains("<col=7f0000>You have 1 minute before your familiar vanishes.")) {
			graahkDisappeared = true;
		} else if (message.contains("You already have a follower.")) {
			graahkAlreadySummoned = true;
		}
	}

	public void onRepaint(Graphics g) {
		if (!bank.isOpen()) {
			Point p1 = null;
			if (getNearestNPCByID(7363) != null)
				highlightTile(g, getNearestNPCByID(7363).getLocation(),
						new Color(0, 255, 0, 80), new Color(0, 0, 255, 20));
			highlightTile(g, getMyPlayer().getLocation(), new Color(0, 255, 0,
					80), new Color(0, 0, 255, 20));
			if (getNearestNPCByID(7363) != null)
				p1 = Calculations.tileToScreen(getNearestNPCByID(7363)
						.getLocation());
			Point p2 = Calculations.tileToScreen(getMyPlayer().getLocation());
			g.setColor(new Color(0, 0, 255, 50));
			if (getNearestNPCByID(7363) != null
					&& tileOnScreen(getNearestNPCByID(7363).getLocation()))
				g.drawLine(p1.x, p1.y, p2.x, p2.y);
		} else {
			final RSInterfaceChild natIF = bank.getItemByID(natID);
			final RSInterfaceChild pessIF = bank.getItemByID(pessID);
			g.setColor(Color.green);
			if (natIF != null && natIF.getAbsoluteY() < 270) {
				g.drawRect(natIF.getAbsoluteX() - 1, natIF.getAbsoluteY() - 1,
						natIF.getWidth() + 2, natIF.getHeight() + 2);
			}
			g.setColor(Color.blue);
			if (pessIF != null && pessIF.getAbsoluteY() < 270) {
				g.drawRect(pessIF.getAbsoluteX() - 1,
						pessIF.getAbsoluteY() - 1, pessIF.getWidth() + 2,
						pessIF.getHeight() + 2);
			}
		}
		if (dest != null) {
			if (pointOnScreen(dest)) {
				// add point to tile
			} else {
				g.setColor(new Color(95, 1, 110, 180));
				g.fillRect(dest.x - 3, dest.y - 3, 6, 6);
			}
		}

		// main paint
		Mouse m = Bot.getClient().getMouse();
		g.setColor(new Color(0, 60, 0, 250));
		g.fillRect(340, 180, 176, 20);
		int XPgain = skills.getCurrentSkillExp(STAT_RUNECRAFTING) - startXP;
		time = (System.currentTimeMillis() - startTime) / 1000;

		// progress tab
		if (SHOWPAINT == 1) {
			g.setColor(new Color(0, 0, 0, 40));
		} else {
			g.setColor(new Color(0, 0, 0, 0));
		}
		g.fillRect(340, 180, 70, 20);
		if (SHOWPAINT == 1) {
			g.setColor(new Color(250, 250, 250, 200));
		} else {
			g.setColor(new Color(250, 250, 250, 100));
		}

		g.drawString("Progress", 345, 193);

		boolean hoverProgress = m.x >= 340 && m.x <= 400 && m.y >= 180
				&& m.y < 200;
		if (hoverProgress) {
			SHOWPAINT = 1;
		}
		if (SHOWPAINT == 1) {
			g.setColor(new Color(250, 250, 250, 40));
			g.fillRect(340, 200, 176, 55);
			g.setColor(new Color(0, 60, 0, 150));
			g.fillRect(340, 200, 176, 110);
			g.setColor(new Color(250, 250, 250, 200));
			g
					.drawString("Aman's Graahk Crafter V2 " + currentVersion,
							350, 230);
			g.drawString("Ran for: " + time / 3600 + ":"
					+ ((time / 60 % 60 < 10) ? "0" : "") + time / 60 % 60 + ":"
					+ ((time % 60 < 10) ? "0" : "") + time % 60, 350, 245);
			g.drawString("Runes Crafted:" + naturerunecount, 350, 260);
			g.drawString("XP Gained:" + XPgain, 350, 275);
			int xptolvl = skills.getXPToNextLevel(STAT_RUNECRAFTING);
			int ptolvl = skills.getPercentToNextLevel(STAT_RUNECRAFTING);
			g.drawString("XP to Lvl:" + xptolvl + " (" + ptolvl + "%)", 350,
					290);

		}
		// calculations tab
		if (SHOWPAINT == 2) {

			g.setColor(new Color(0, 0, 0, 40));
		} else {
			g.setColor(new Color(0, 0, 0, 0));
		}
		g.fillRect(410, 180, 106, 20);
		if (SHOWPAINT == 2) {
			g.setColor(new Color(250, 250, 250, 200));
		} else {
			g.setColor(new Color(250, 250, 250, 100));
		}
		g.drawString("Calculations", 415, 193);

		boolean hoverCalculations = m.x >= 410 && m.x <= 516 && m.y >= 180
				&& m.y < 200;
		if (hoverCalculations) {
			SHOWPAINT = 2;
		}
		if (SHOWPAINT == 2) {

			long runTime = 0;
			long seconds = 0;
			long minutes = 0;
			long hours = time / 3600;
			runTime = (System.currentTimeMillis() - scriptStartTime);
			seconds = runTime / 1000;
			if (seconds >= 60) {
				minutes = seconds / 60;
				seconds -= (minutes * 60);
			}
			if (minutes >= 60) {
				hours = minutes / 60;
				minutes -= (hours * 60);
			}

			g.setColor(new Color(250, 250, 250, 40));
			g.fillRect(340, 200, 176, 55);
			g.setColor(new Color(0, 60, 0, 150));
			g.fillRect(340, 200, 176, 110);
			g.setColor(new Color(250, 250, 250, 200));
			g.drawString("Runes/Hour:" + (naturerunecount * 60 * 60) / time,
					350, 230);
			g.drawString("XP/Hour:" + (XPgain * 60 * 60) / time, 350, 245);
			g.drawString("Nat price:" + natPrice, 350, 260);
			g.drawString("Pure Ess price:" + pessPrice, 350, 275);
			int profit;
			if (skills.getCurrentSkillLevel(STAT_RUNECRAFTING) >= 91)
				profit = (natPrice * naturerunecount)
						- (pessPrice * (naturerunecount / 2));
			else
				profit = (natPrice - pessPrice) * naturerunecount;
			g.drawString("Profit:" + profit, 350, 290);
			g.drawString("Profit/Hour:" + (profit * 60 * 60) / time, 350, 305);

		}
		// boxes
		g.setColor(new Color(0, 0, 0, 100));
		if (checkspouch) {
			g.fillRect(426, 206, 6, 6);
		} else {
			g.drawRect(426, 206, 6, 6);
		}
		if (checkmpouch) {
			g.fillRect(444, 205, 8, 8);
		} else {
			g.drawRect(444, 205, 8, 8);
		}
		if (checklpouch) {
			g.fillRect(464, 204, 10, 10);
		} else {
			g.drawRect(464, 204, 10, 10);
		}
		if (checkgpouch) {
			g.fillRect(488, 203, 12, 12);
		} else {
			g.drawRect(488, 203, 12, 12);
		}

		// mouse
		Point p = getMouseLocation();
		long timeSince = Bot.getClient().getMouse().getMousePressTime();
		if (timeSince > System.currentTimeMillis() - 500)
			g.setColor(new Color(0, 140, 0, 150));

		else
			g.setColor(new Color(0, 140, 0, 250));

		g.drawOval((p.x - 3), (p.y - 3), 6, 6);
		g.fillOval((p.x - 3), (p.y - 3), 6, 6);
		g.drawOval(p.x - 6, p.y - 6, 12, 12);
		Stroke drawingStroke = new BasicStroke(1, BasicStroke.CAP_SQUARE,
				BasicStroke.JOIN_ROUND, 1, new float[] { 2 }, 1);
		Line2D line = new Line2D.Double(p.x, 0, p.x, 500);
		Graphics2D g2d = (Graphics2D) g;
		g2d.setStroke(drawingStroke);
		g2d.draw(line);
		Stroke drawingStroke1 = new BasicStroke(1, BasicStroke.CAP_SQUARE,
				BasicStroke.JOIN_ROUND, 1, new float[] { 2 }, 1);
		Line2D line1 = new Line2D.Double(0, p.y, 762, p.y);
		Graphics2D g2d1 = (Graphics2D) g;
		g2d1.setStroke(drawingStroke1);
		g2d1.draw(line1);
	}

	// banking methods
	private void withdraw(final int ID, final String name, final boolean all) {
		if (failcount > 15) {
			log("Unable to withraw " + name
					+ ". You will be logged out in ten seconds.");
			wait(random(9000, 11000));
			while (bank.isOpen()) {
				closeBank();
			}
			stopAllScripts();
		}
		RSInterfaceChild bankItem = bank.getItemByID(ID);
		if (bankItem == null) {
			failcount++;
			bankItem = bank.getItemByID(ID);
		} else if (bankItem.getAbsoluteY() > 270) {
			clickMouse(85, 308, 4, 5, true, 50);
			wait(random(1200, 1500));
			final int rand = random(0, Math.min(4, name.length() - 2));
			sendText(name.toLowerCase().substring(0, name.length() - rand),
					false);
			wait(random(900, 1200));
			bankItem = bank.getItemByID(ID);
			if (bankItem == null
					|| bankItem.getAbsoluteY() > 270
					|| !bank.atItem(ID, all ? "Withdraw-All " + name
							: "Withdraw-1 " + name)
					&& !bank.atItem(ID, all ? "Withdraw-All " + name
							: "Withdraw-1 " + name)) {
				failcount++;
				withdraw(ID, name, all);
			} else {
				clickMouse(50, 66, 7, 7, true);
			}
		} else {
			bank
					.atItem(ID, all ? "Withdraw-All " + name : "Withdraw-1 "
							+ name);
		}
	}

	private void closeBank() {
		clickMouse(489, 35, 3, 3, true, 20);
	}

	public int sleepTime() {
		int time = sleepTime + random(-40, 40);
		return time;
	}

	// get action
	public Action getAction() {
		if (ringDisappeared == true
				&& getNearestObjectByID(bankChestID) != null) {
			return Action.WITHDRAW_RING;
		}

		if (graahkDisappeared == true
				&& getNearestObjectByID(bankChestID) != null
				&& !ringDisappeared) {
			return Action.SUMMON;
		}

		if ((getNearestObjectByID(bankChestID) != null) && fillPouches
				&& !filledPouches && !ringDisappeared && !graahkDisappeared) {
			return Action.FILL;
		}

		if (getInventoryCount(pessID) < 20
				&& (getNearestObjectByID(bankChestID) != null) && !fillPouches
				&& !ringDisappeared && !graahkDisappeared) {
			return Action.BANK;
		}

		if (getInventoryCount(pessID) >= 20 && !tileOnMap(teleportTile)
				&& getNearestObjectByID(bankChestID) != null && !fillPouches
				&& !ringDisappeared && !graahkDisappeared) {
			return Action.GRAAHK;
		}

		if (getNearestObjectByID(ruinsID) == null
				&& getNearestObjectByID(altarID) == null
				&& getNearestObjectByID(bankChestID) == null) {
			return Action.WALK;
		}

		if (getNearestObjectByID(ruinsID) != null) {
			return Action.ENTER;
		}

		if (getInventoryCount(pessID) >= 17
				&& getNearestObjectByID(altarID) != null
				&& getNearestObjectByID(ruinsID) == null) {
			return Action.CRAFT;
		}

		if (getInventoryCount(pessID) == 0
				&& getNearestObjectByID(altarID) != null
				&& getNearestObjectByID(ruinsID) == null) {
			return Action.RING;
		}
		return null;
	}

	// checks of character has a equipment on
	/*
	 * private boolean equipmentContainsAny(int ... items) { for(int item :
	 * getEquipmentArray()) for(int id : items) if(item == id) return true;
	 * return false; }
	 */
	// pouching methods
	private void emptyPouches() {
		openTab(TAB_INVENTORY);
		if (checkspouch)
			pouchEmpty(smallpouch);
		if (checkmpouch) {
			if (inventoryContains(mediumpouch))
				pouchEmpty(mediumpouch);
			else
				pouchEmpty(mediumpouchdecay);
		}
		if (checklpouch) {
			if (inventoryContains(largepouch))
				pouchEmpty(largepouch);
			else
				pouchEmpty(largepouchdecay);
		}
		if (checkgpouch) {
			if (inventoryContains(giantpouch))
				pouchEmpty(giantpouch);
			else
				pouchEmpty(giantpouchdecay);
		}
		emptiedPouches = true;
	}

	private boolean leftClickInventoryItem(int itemID) {
		if (getCurrentTab() != TAB_INVENTORY
				&& !RSInterface.getInterface(INTERFACE_BANK).isValid()
				&& !RSInterface.getInterface(INTERFACE_STORE).isValid()) {
			openTab(TAB_INVENTORY);
		}
		int[] items = getInventoryArray();
		java.util.List<Integer> possible = new ArrayList<Integer>();
		for (int i = 0; i < items.length; i++) {
			if (items[i] == itemID) {
				possible.add(i);
			}
		}
		if (possible.size() == 0)
			return false;
		int idx = possible.get(0);
		Point t = getInventoryItemPoint(idx);
		int x = t.x;
		x += random(1, 35);
		int y = t.y;
		y += random(1, 30);
		Point f = new Point(x, y);
		clickMouse(f, 0, 0, true);
		return true;
	}

	public boolean pouchFill(int i) {
		int startCount = getInventoryCount(pessID);
		leftClickInventoryItem(i);
		if (i == smallpouch) {
			if (inventoryContains(mediumpouch)) {
				hoverPouch(mediumpouch);
			} else {
				hoverPouch(mediumpouchdecay);
			}
		} else if (i == mediumpouch || i == mediumpouchdecay) {
			if (inventoryContains(largepouch)) {
				hoverPouch(largepouch);
			} else {
				hoverPouch(largepouchdecay);
			}
		} else if (i == largepouch || i == largepouchdecay) {
			if (inventoryContains(giantpouch)) {
				hoverPouch(giantpouch);
			} else {
				hoverPouch(giantpouchdecay);
			}
		}
		wait(sleepTime());
		int endCount = getInventoryCount(pessID);
		if ((endCount < startCount) || failcount >= 5) {
			failcount = 0;
			return true;
		} else {
			failcount++;
			pouchFill(i);
		}
		return false;
	}

	public boolean pouchEmpty(int i) {
		int startCount = getInventoryCount(pessID);
		atInventoryItem(i, "mpty");
		if (i == smallpouch) {
			if (inventoryContains(mediumpouch)) {
				hoverPouch(mediumpouch);
			} else {
				hoverPouch(mediumpouchdecay);
			}
		} else if (i == mediumpouch || i == mediumpouchdecay) {
			if (inventoryContains(largepouch)) {
				hoverPouch(largepouch);
			} else {
				hoverPouch(largepouchdecay);
			}
		} else if (i == largepouch || i == largepouchdecay) {
			if (inventoryContains(giantpouch)) {
				hoverPouch(giantpouch);
			} else {
				hoverPouch(giantpouchdecay);
			}
		}
		wait(sleepTime());
		int endCount = getInventoryCount(pessID);
		if ((endCount > startCount) || failcount >= 5) {
			failcount = 0;
			return true;
		} else {
			failcount++;
			pouchEmpty(i);
		}
		return false;
	}

	public boolean hoverPouch(int itemID) {
		int[] pouch = getInventoryArray();
		java.util.List<Integer> possible = new ArrayList<Integer>();
		for (int i = 0; i < pouch.length; i++) {
			if (pouch[i] == itemID) {
				possible.add(i);
			}
		}
		if (possible.size() == 0)
			return false;
		int idx = possible.get(0);
		Point t = getInventoryItemPoint(idx);
		if (betweenPoints(getMouseLocation(), t) > 7) {
			moveMouse(t, 5, 5);
			return true;
		} else {
			return true;
		}
	}

	public double betweenPoints(Point x, Point y) {
		return (Math.hypot((x.x - y.x), (x.y - y.y)));
	}

	// paint
	private void highlightTile(final Graphics g, final RSTile t,
			final Color outline, final Color fill) {
		final Point pn = Calculations.tileToScreen(t.getX(), t.getY(), 0, 0, 0);
		final Point px = Calculations.tileToScreen(t.getX() + 1, t.getY(), 0,
				0, 0);
		final Point py = Calculations.tileToScreen(t.getX(), t.getY() + 1, 0,
				0, 0);
		final Point pxy = Calculations.tileToScreen(t.getX() + 1, t.getY() + 1,
				0, 0, 0);
		if (py.x == -1 || pxy.x == -1 || px.x == -1 || pn.x == -1) {
			return;
		}
		g.setColor(outline);
		g.drawPolygon(new int[] { py.x, pxy.x, px.x, pn.x }, new int[] { py.y,
				pxy.y, px.y, pn.y }, 4);
		g.setColor(fill);
		g.fillPolygon(new int[] { py.x, pxy.x, px.x, pn.x }, new int[] { py.y,
				pxy.y, px.y, pn.y }, 4);
	}

	private RSTile getRandomTileInArea(int maxX, int maxY, int minX, int minY) {
		int possibleX = maxX - minX;
		int possibleY = maxY - minY;
		int[] tileY = new int[possibleY];
		int[] tileX = new int[possibleX];
		for (int i = 0; i < (tileY.length); i++) {
			tileY[i] = minY + i;
		}
		for (int i = 0; i < (tileX.length); i++) {
			tileX[i] = minX + i;
		}
		int x = (int) (Math.random() * possibleX + 0);
		int y = (int) (Math.random() * possibleY + 0);
		RSTile tile = new RSTile(tileX[x], tileY[y]);
		log(Arrays.toString(tileX));
		log(Arrays.toString(tileY));
		log("Tile returned " + tile);
		if (tileOnMap(tile))
			return tile;
		else
			return null;
	}

	private boolean walkTo(final RSTile tile) {
		RSTile dest = getMyPlayer().getLocation();
		RSTile[] path = null;
		while (distanceTo(tile) > 3 || !tileOnScreen(tile)) {
			if (Methods.distanceBetween(tile, dest) > 1) {
				dest = getClosestTileInRegion(tile);
				path = pathFinder.findPath(getMyPlayer().getLocation(), dest);
			}
			if (path == null) {
				return walkTileMM(checkTile(tile));
			}
			for (int i = path.length - 1; i >= 0; i--) {
				if (distanceTo(path[i]) < 17
						&& getRealDistanceTo(path[i], false) < 60) {
					if (getDestination() != null) {
						try {
							if (Methods.distanceBetween(getDestination(),
									path[i]) <= 3) {
								break;
							}
						} catch (final Exception e) {
							log.info("Walking Error");
						}
					}
					walkTileMM(checkTile(path[i]), 1, 1);
					wait(random(600, 1000));
					final RSTile cdest = getDestination();
					if (cdest != null && distanceTo(cdest) > 6) {
						wait(random(1000, 1200));
					}
					break;
				}
			}
			wait(random(50, 100));
		}
		return true;
	}

	private RSTile getClosestTileInRegion(final RSTile tile) {
		if (tileInRegion(tile)) {
			return tile;
		}
		final RSTile loc = getMyPlayer().getLocation();
		final RSTile walk = new RSTile((loc.getX() + tile.getX()) / 2, (loc
				.getY() + tile.getY()) / 2);

		return tileInRegion(walk) ? walk : getClosestTileInRegion(walk);
	}

	private RSTile checkTile(final RSTile tile) {
		if (distanceTo(tile) < 17) {
			return tile;
		}
		final RSTile loc = getMyPlayer().getLocation();
		final RSTile walk = new RSTile((loc.getX() + tile.getX()) / 2, (loc
				.getY() + tile.getY()) / 2);
		return distanceTo(walk) < 17 ? walk : checkTile(walk);
	}

	private boolean tileInRegion(final RSTile tile) {
		final int tileX = tile.getX() - Bot.getClient().getBaseX(), tileY = tile
				.getY()
				- Bot.getClient().getBaseY();
		return !(tileX < 0 || tileY < 0 || tileX > 103 || tileY > 103);
	}

	public long timeToNext;

	// credits to DDM
	public class antiban extends Thread {

		public void checkFriendsList() {
			openTab(Constants.TAB_FRIENDS);
			moveMouse(random(554, 709), random(227, 444));
		}

		public void checkSkills() {
			openTab(Constants.TAB_STATS);
			moveMouse(random(552, 603), random(420, 449));
		}

		public int getRandomMouseX(final int maxDistance) {
			final Point p = getMouseLocation();
			if (random(0, 2) == 0) {
				return p.x - random(0, p.x < maxDistance ? p.x : maxDistance);
			} else {
				return p.x
						+ random(1, 762 - p.x < maxDistance ? 762 - p.x
								: maxDistance);
			}
		}

		public int getRandomMouseY(final int maxDistance) {
			final Point p = getMouseLocation();
			if (random(0, 2) == 0) {
				return p.y - random(0, p.y < maxDistance ? p.y : maxDistance);
			} else {
				return p.y
						+ random(1, 500 - p.y < maxDistance ? 500 - p.y
								: maxDistance);
			}
		}

		public boolean moveMouseRandomly(int maxDistance) {
			if (maxDistance == 0) {
				return false;
			}
			maxDistance = random(1, maxDistance);
			final Point p = new Point(getRandomMouseX(maxDistance),
					getRandomMouseY(maxDistance));
			if (p.x < 1 || p.y < 1) {
				p.x = p.y = 1;
			}
			moveMouse(p);
			if (random(0, 2) == 0) {
				return false;
			}
			return moveMouseRandomly(maxDistance / 2);
		}

		public long nextTime(final int waitTime) {
			return time() + waitTime;
		}

		public long nextTime(final int min, final int max) {
			return nextTime(random(min, max));
		}

		@Override
		public void run() {
			log("Antiban running");
			try {
				final int roll = (int) (Math.random() * 1000);
				if (timeToNext < time()) {
					if (roll > 995) {
					} else if (roll > 990 && getInventoryCount() < 23) {
						checkSkills();
						timeToNext = System.currentTimeMillis()
								+ random(2000, 25000);
					} else if (roll > 985
							&& getInventoryCount() < 23
							&& !RSInterface.getInterface(751).getChild(15)
									.getText().contains("Off")) {
						checkFriendsList();
						timeToNext = System.currentTimeMillis()
								+ random(2000, 25000);
					} else if (roll > 980 && getInventoryCount() < 23) {
						checkSkills();
						timeToNext = System.currentTimeMillis()
								+ random(2000, 25000);
					} else if (roll > 960) {
						if (random(0, 2) == 0) {
							setCameraRotation((int) (getCameraAngle() + (Math
									.random() * 50 > 25 ? 1 : -1)
									* (30 + Math.random() * 90)));
						} else {
							final int key = random(0, 3) < 0 ? KeyEvent.VK_UP
									: KeyEvent.VK_DOWN;
							Bot.getInputManager().pressKey((char) key);
							Thread.sleep(random(1000, 1500));
							Bot.getInputManager().releaseKey((char) key);
						}
					} else if (roll > 940) {
						timeToNext = System.currentTimeMillis()
								+ random(2000, 25000);
						openTab(Constants.TAB_INVENTORY);
					} else if (roll > 890 && !isRunning()
							&& getMyPlayer().isMoving()) {
						if (getEnergy() > 50) {
							clickMouse(random(707, 762), random(90, 121), true);
							timeToNext = nextTime(500, 1200);
						} else if (rest) {
							Rest(100);
							Run(true);
							timeToNext = nextTime(500, 1200);
						}
						Thread.sleep(random(300, 1000));
					} else if (roll > 780) {
						moveMouseRandomly(500);
						timeToNext = nextTime(500, 7500);
					}
				} else {
					Thread.yield();
				}
			} catch (final InterruptedException e) {
				log("Interrupted");
			}
		}

		public long time() {
			return System.currentTimeMillis();
		}

		public boolean timePassed(final long time) {
			return time() > time;
		}

		public void turnCameraRandom() {
			setCameraRotation((int) (getCameraAngle() + (Math.random() * 50 > 25 ? 1
					: -1)
					* (30 + Math.random() * 90)));
		}
	}

	public void Rest(final int stopEnergy) {
		rest(stopEnergy);
	}

	/*
	 * public int getInventoryCount(int item){ int count = 0; int[] itemarray =
	 * getInventoryArray(); for(int i: itemarray){ if(itemarray[i] == item)
	 * count++; } log(""+count); return count; }
	 */
	public boolean Run(final boolean running) {
		try {
			final long startTime = System.currentTimeMillis();
			while (System.currentTimeMillis() - startTime < 2000) {
				if (running) {
					while (!isRunning()) {
						wait(random(200, 230));
					}
					return true;
				} else {
					while (isRunning()) {
						wait(random(200, 230));
					}
					return true;
				}
			}
			return false;
		} catch (final Exception e) {
			return false;
		}
	}

	public class graahkcraftgui extends javax.swing.JFrame {

		private static final long serialVersionUID = -4993921042786766283L;

		/** Creates new form graahkcraftgui */
		public graahkcraftgui() {
			initComponents();
		}

		/**
		 * This method is called from within the constructor to initialize the
		 * form. WARNING: Do NOT modify this code. The content of this method is
		 * always regenerated by the Form Editor.
		 */
		@SuppressWarnings("unchecked")
		// <editor-fold defaultstate="collapsed" desc="Generated Code">
		private void initComponents() {

			jTabbedPane1 = new javax.swing.JTabbedPane();
			jPanel1 = new javax.swing.JPanel();
			giantCheckBox = new javax.swing.JCheckBox();
			usePouchesCheckBox = new javax.swing.JCheckBox();
			smallCheckBox = new javax.swing.JCheckBox();
			mediumCheckBox = new javax.swing.JCheckBox();
			largeCheckBox = new javax.swing.JCheckBox();
			sleepSlider = new javax.swing.JSlider();
			jLabel1 = new javax.swing.JLabel();
			jLabel2 = new javax.swing.JLabel();
			mouseSlider = new javax.swing.JSlider();
			pathTypeComboBox = new javax.swing.JComboBox();
			jLabel3 = new javax.swing.JLabel();
			jPanel2 = new javax.swing.JPanel();
			jScrollPane1 = new javax.swing.JScrollPane();
			jTextArea1 = new javax.swing.JTextArea();
			jPanel3 = new javax.swing.JPanel();
			jButton4 = new javax.swing.JButton();
			jButton2 = new javax.swing.JButton();
			jButton3 = new javax.swing.JButton();
			jButton1 = new javax.swing.JButton();

			setTitle("Aman's Graahk Craft V2");
			setAlwaysOnTop(true);
			setResizable(false);

			jTabbedPane1.setBackground(new java.awt.Color(204, 255, 204));

			jPanel1.setBackground(new java.awt.Color(204, 255, 204));
			jPanel1.setToolTipText("Lower value means smaller wait times");

			giantCheckBox.setBackground(new java.awt.Color(204, 255, 204));
			giantCheckBox.setText("Giant");
			giantCheckBox
					.addActionListener(new java.awt.event.ActionListener() {
						public void actionPerformed(
								java.awt.event.ActionEvent evt) {
							giantCheckBoxActionPerformed(evt);
						}
					});

			usePouchesCheckBox.setBackground(new java.awt.Color(204, 255, 204));
			usePouchesCheckBox.setText("Use pouches:");
			usePouchesCheckBox
					.addActionListener(new java.awt.event.ActionListener() {
						public void actionPerformed(
								java.awt.event.ActionEvent evt) {
							usePouchesCheckBoxActionPerformed(evt);
						}
					});

			smallCheckBox.setBackground(new java.awt.Color(204, 255, 204));
			smallCheckBox.setText("Small");

			mediumCheckBox.setBackground(new java.awt.Color(204, 255, 204));
			mediumCheckBox.setText("Medium");

			largeCheckBox.setBackground(new java.awt.Color(204, 255, 204));
			largeCheckBox.setText("Large");

			sleepSlider.setBackground(new java.awt.Color(204, 255, 204));
			sleepSlider.setFont(new java.awt.Font("Tahoma", 0, 8)); // NOI18N
			sleepSlider.setMajorTickSpacing(50);
			sleepSlider.setMaximum(650);
			sleepSlider.setMinimum(250);
			sleepSlider.setMinorTickSpacing(1);
			sleepSlider.setPaintLabels(true);
			sleepSlider.setPaintTicks(true);
			sleepSlider.setToolTipText("Lower value means smaller wait times");
			sleepSlider.setValue(400);

			jLabel1.setFont(new java.awt.Font("Tahoma", 1, 11));
			jLabel1.setForeground(new java.awt.Color(102, 102, 102));
			jLabel1.setText("Sleep time");

			jLabel2.setFont(new java.awt.Font("Tahoma", 1, 11));
			jLabel2.setForeground(new java.awt.Color(102, 102, 102));
			jLabel2.setText("Mouse speed");

			mouseSlider.setBackground(new java.awt.Color(204, 255, 204));
			mouseSlider.setMajorTickSpacing(1);
			mouseSlider.setMaximum(10);
			mouseSlider.setMinimum(5);
			mouseSlider.setMinorTickSpacing(1);
			mouseSlider.setPaintLabels(true);
			mouseSlider.setPaintTicks(true);
			mouseSlider.setSnapToTicks(true);
			mouseSlider.setToolTipText("Lower value means faster mouse ");
			mouseSlider.setValue(8);

			pathTypeComboBox.setModel(new javax.swing.DefaultComboBoxModel(
					new String[] { "Default", "Random" }));
			pathTypeComboBox
					.setToolTipText("Default - walks the normal RCer path           Random - walks a random path everytime");

			jLabel3.setText("Path type:");

			javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(
					jPanel1);
			jPanel1.setLayout(jPanel1Layout);
			jPanel1Layout
					.setHorizontalGroup(jPanel1Layout
							.createParallelGroup(
									javax.swing.GroupLayout.Alignment.LEADING)
							.addGroup(
									jPanel1Layout
											.createSequentialGroup()
											.addGroup(
													jPanel1Layout
															.createParallelGroup(
																	javax.swing.GroupLayout.Alignment.LEADING)
															.addGroup(
																	jPanel1Layout
																			.createSequentialGroup()
																			.addGroup(
																					jPanel1Layout
																							.createParallelGroup(
																									javax.swing.GroupLayout.Alignment.LEADING)
																							.addGroup(
																									jPanel1Layout
																											.createSequentialGroup()
																											.addGap(
																													28,
																													28,
																													28)
																											.addGroup(
																													jPanel1Layout
																															.createParallelGroup(
																																	javax.swing.GroupLayout.Alignment.LEADING)
																															.addComponent(
																																	mediumCheckBox)
																															.addComponent(
																																	smallCheckBox)
																															.addComponent(
																																	largeCheckBox)
																															.addComponent(
																																	giantCheckBox)))
																							.addGroup(
																									jPanel1Layout
																											.createSequentialGroup()
																											.addContainerGap()
																											.addComponent(
																													usePouchesCheckBox)))
																			.addGap(
																					1,
																					1,
																					1)
																			.addGroup(
																					jPanel1Layout
																							.createParallelGroup(
																									javax.swing.GroupLayout.Alignment.LEADING)
																							.addGroup(
																									jPanel1Layout
																											.createSequentialGroup()
																											.addGap(
																													98,
																													98,
																													98)
																											.addGroup(
																													jPanel1Layout
																															.createParallelGroup(
																																	javax.swing.GroupLayout.Alignment.LEADING)
																															.addComponent(
																																	jLabel2)
																															.addComponent(
																																	jLabel1))
																											.addGap(
																													150,
																													150,
																													150))
																							.addGroup(
																									javax.swing.GroupLayout.Alignment.TRAILING,
																									jPanel1Layout
																											.createSequentialGroup()
																											.addPreferredGap(
																													javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																											.addGroup(
																													jPanel1Layout
																															.createParallelGroup(
																																	javax.swing.GroupLayout.Alignment.LEADING)
																															.addComponent(
																																	sleepSlider,
																																	javax.swing.GroupLayout.PREFERRED_SIZE,
																																	javax.swing.GroupLayout.DEFAULT_SIZE,
																																	javax.swing.GroupLayout.PREFERRED_SIZE)
																															.addComponent(
																																	mouseSlider,
																																	javax.swing.GroupLayout.PREFERRED_SIZE,
																																	javax.swing.GroupLayout.DEFAULT_SIZE,
																																	javax.swing.GroupLayout.PREFERRED_SIZE))
																											.addGap(
																													42,
																													42,
																													42))))
															.addGroup(
																	jPanel1Layout
																			.createSequentialGroup()
																			.addGap(
																					36,
																					36,
																					36)
																			.addComponent(
																					jLabel3)
																			.addGap(
																					18,
																					18,
																					18)
																			.addComponent(
																					pathTypeComboBox,
																					javax.swing.GroupLayout.PREFERRED_SIZE,
																					javax.swing.GroupLayout.DEFAULT_SIZE,
																					javax.swing.GroupLayout.PREFERRED_SIZE)))
											.addContainerGap(
													javax.swing.GroupLayout.DEFAULT_SIZE,
													Short.MAX_VALUE)));

			jPanel1Layout.linkSize(javax.swing.SwingConstants.HORIZONTAL,
					new java.awt.Component[] { mouseSlider, sleepSlider });

			jPanel1Layout
					.setVerticalGroup(jPanel1Layout
							.createParallelGroup(
									javax.swing.GroupLayout.Alignment.LEADING)
							.addGroup(
									jPanel1Layout
											.createSequentialGroup()
											.addGap(18, 18, 18)
											.addGroup(
													jPanel1Layout
															.createParallelGroup(
																	javax.swing.GroupLayout.Alignment.BASELINE)
															.addComponent(
																	usePouchesCheckBox)
															.addComponent(
																	jLabel1))
											.addGroup(
													jPanel1Layout
															.createParallelGroup(
																	javax.swing.GroupLayout.Alignment.LEADING)
															.addGroup(
																	jPanel1Layout
																			.createSequentialGroup()
																			.addPreferredGap(
																					javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																			.addComponent(
																					smallCheckBox)
																			.addPreferredGap(
																					javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																			.addComponent(
																					mediumCheckBox)
																			.addPreferredGap(
																					javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																			.addComponent(
																					largeCheckBox)
																			.addPreferredGap(
																					javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																			.addComponent(
																					giantCheckBox))
															.addGroup(
																	jPanel1Layout
																			.createSequentialGroup()
																			.addGap(
																					41,
																					41,
																					41)
																			.addComponent(
																					jLabel2)
																			.addPreferredGap(
																					javax.swing.LayoutStyle.ComponentPlacement.RELATED)
																			.addComponent(
																					mouseSlider,
																					javax.swing.GroupLayout.PREFERRED_SIZE,
																					javax.swing.GroupLayout.DEFAULT_SIZE,
																					javax.swing.GroupLayout.PREFERRED_SIZE)))
											.addPreferredGap(
													javax.swing.LayoutStyle.ComponentPlacement.RELATED,
													javax.swing.GroupLayout.DEFAULT_SIZE,
													Short.MAX_VALUE)
											.addGroup(
													jPanel1Layout
															.createParallelGroup(
																	javax.swing.GroupLayout.Alignment.BASELINE)
															.addComponent(
																	pathTypeComboBox,
																	javax.swing.GroupLayout.PREFERRED_SIZE,
																	javax.swing.GroupLayout.DEFAULT_SIZE,
																	javax.swing.GroupLayout.PREFERRED_SIZE)
															.addComponent(
																	jLabel3))
											.addContainerGap())
							.addGroup(
									javax.swing.GroupLayout.Alignment.TRAILING,
									jPanel1Layout
											.createSequentialGroup()
											.addContainerGap(38,
													Short.MAX_VALUE)
											.addComponent(
													sleepSlider,
													javax.swing.GroupLayout.PREFERRED_SIZE,
													javax.swing.GroupLayout.DEFAULT_SIZE,
													javax.swing.GroupLayout.PREFERRED_SIZE)
											.addGap(105, 105, 105)));

			jTabbedPane1.addTab("Main", jPanel1);

			jPanel2.setBackground(new java.awt.Color(255, 204, 204));

			jTextArea1.setBackground(new java.awt.Color(255, 204, 204));
			jTextArea1.setColumns(20);
			jTextArea1.setRows(5);
			jTextArea1
					.setText("Aman's Graahk Crafter V2 by aman\n\nThanks to \ncreative\ndarkdefiant\nhundescheise");
			jScrollPane1.setViewportView(jTextArea1);

			javax.swing.GroupLayout jPanel2Layout = new javax.swing.GroupLayout(
					jPanel2);
			jPanel2.setLayout(jPanel2Layout);
			jPanel2Layout.setHorizontalGroup(jPanel2Layout.createParallelGroup(
					javax.swing.GroupLayout.Alignment.LEADING).addComponent(
					jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 391,
					Short.MAX_VALUE));
			jPanel2Layout.setVerticalGroup(jPanel2Layout.createParallelGroup(
					javax.swing.GroupLayout.Alignment.LEADING).addComponent(
					jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 184,
					Short.MAX_VALUE));

			jTabbedPane1.addTab("Credits", jPanel2);

			jPanel3.setBackground(new java.awt.Color(204, 204, 255));

			jButton4.setFont(new java.awt.Font("Verdana", 0, 11)); // NOI18N
			jButton4.setText("You know whats in here");
			jButton4.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent evt) {
					jButton4ActionPerformed(evt);
				}
			});

			javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(
					jPanel3);
			jPanel3.setLayout(jPanel3Layout);
			jPanel3Layout
					.setHorizontalGroup(jPanel3Layout
							.createParallelGroup(
									javax.swing.GroupLayout.Alignment.LEADING)
							.addGroup(
									jPanel3Layout
											.createSequentialGroup()
											.addGap(55, 55, 55)
											.addComponent(
													jButton4,
													javax.swing.GroupLayout.PREFERRED_SIZE,
													248,
													javax.swing.GroupLayout.PREFERRED_SIZE)
											.addContainerGap(88,
													Short.MAX_VALUE)));
			jPanel3Layout
					.setVerticalGroup(jPanel3Layout
							.createParallelGroup(
									javax.swing.GroupLayout.Alignment.LEADING)
							.addGroup(
									jPanel3Layout
											.createSequentialGroup()
											.addGap(32, 32, 32)
											.addComponent(
													jButton4,
													javax.swing.GroupLayout.PREFERRED_SIZE,
													109,
													javax.swing.GroupLayout.PREFERRED_SIZE)
											.addContainerGap(43,
													Short.MAX_VALUE)));

			jTabbedPane1.addTab("Free porn", jPanel3);

			jButton2.setText("Forum");
			jButton2.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent evt) {
					jButton2ActionPerformed(evt);
				}
			});

			jButton3.setText("Update");
			jButton3.setEnabled(false);
			jButton3.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent evt) {
					jButton3ActionPerformed(evt);
				}
			});

			jButton1.setFont(new java.awt.Font("SansSerif", 1, 11)); // NOI18N
			jButton1.setText("START");
			jButton1.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent evt) {
					jButton1ActionPerformed(evt);
				}
			});

			javax.swing.GroupLayout layout = new javax.swing.GroupLayout(
					getContentPane());
			getContentPane().setLayout(layout);
			layout
					.setHorizontalGroup(layout
							.createParallelGroup(
									javax.swing.GroupLayout.Alignment.LEADING)
							.addGroup(
									layout
											.createSequentialGroup()
											.addContainerGap()
											.addComponent(jButton2)
											.addPreferredGap(
													javax.swing.LayoutStyle.ComponentPlacement.RELATED,
													147, Short.MAX_VALUE)
											.addComponent(jButton3)
											.addPreferredGap(
													javax.swing.LayoutStyle.ComponentPlacement.RELATED)
											.addComponent(jButton1).addGap(34,
													34, 34)).addComponent(
									jTabbedPane1,
									javax.swing.GroupLayout.DEFAULT_SIZE, 396,
									Short.MAX_VALUE));
			layout
					.setVerticalGroup(layout
							.createParallelGroup(
									javax.swing.GroupLayout.Alignment.LEADING)
							.addGroup(
									javax.swing.GroupLayout.Alignment.TRAILING,
									layout
											.createSequentialGroup()
											.addComponent(
													jTabbedPane1,
													javax.swing.GroupLayout.DEFAULT_SIZE,
													212, Short.MAX_VALUE)
											.addPreferredGap(
													javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
											.addGroup(
													layout
															.createParallelGroup(
																	javax.swing.GroupLayout.Alignment.BASELINE)
															.addComponent(
																	jButton2)
															.addComponent(
																	jButton3)
															.addComponent(
																	jButton1))
											.addContainerGap()));

			pack();
		}// </editor-fold>

		private void giantCheckBoxActionPerformed(java.awt.event.ActionEvent evt) {
			// TODO add your handling code here:
		}

		private void usePouchesCheckBoxActionPerformed(
				java.awt.event.ActionEvent evt) {
			// TODO add your handling code here:
		}

		private void jButton2ActionPerformed(java.awt.event.ActionEvent evt) {
			if (!java.awt.Desktop.isDesktopSupported()) {
				log("Unable to open page. You can manually open the page; the url is http://www.rsbot.org/vb/showthread.php?t=116644");
				return;
			}
			java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
			if (!desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
				log("Unable to open page. You can manually open the page; the url is http://www.rsbot.org/vb/showthread.php?t=116644");
				return;
			}
			try {
				desktop.browse(new URI(
						"http://www.rsbot.org/vb/showthread.php?t=116644"));
				log("Successfully opened page.");
			} catch (Exception e) {
				log(e.getMessage());
				return;
			}
		}

		private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
			// update
		}

		private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {
			if (usePouchesCheckBox.isSelected()) {
				usePouches = true;
				if (smallCheckBox.isSelected())
					checkspouch = true;
				if (mediumCheckBox.isSelected())
					checkmpouch = true;
				if (largeCheckBox.isSelected())
					checklpouch = true;
				if (giantCheckBox.isSelected())
					checkgpouch = true;
			}
			if (pathTypeComboBox.getSelectedItem().equals("Default")) {
				normalPath = true;
			}
			mouseSpeed = mouseSlider.getValue();
			sleepTime = sleepSlider.getValue();
			setVisible(false);
			startScript = true;
		}

		private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {
			// paypal link
			// https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7582494
			if (!java.awt.Desktop.isDesktopSupported()) {
				log("Unable to open page. You can manually open the page; the url is https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7582494");
				return;
			}
			java.awt.Desktop desktop = java.awt.Desktop.getDesktop();
			if (!desktop.isSupported(java.awt.Desktop.Action.BROWSE)) {
				log("Unable to open page. You can manually open the page; the url is https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7582494");
				return;
			}
			try {
				desktop
						.browse(new URI(
								"https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=7582494"));
				log("Successfully opened page.");
			} catch (Exception e) {
				log(e.getMessage());
				return;
			}
		}

		/**
		 * @param args
		 *            the command line arguments
		 */
		public void main(String args[]) {
			java.awt.EventQueue.invokeLater(new Runnable() {
				public void run() {
					new graahkcraftgui().setVisible(true);
				}
			});
		}

		// Variables declaration - do not modify
		private javax.swing.JCheckBox giantCheckBox;
		private javax.swing.JButton jButton1;
		private javax.swing.JButton jButton2;
		private javax.swing.JButton jButton3;
		private javax.swing.JButton jButton4;
		private javax.swing.JLabel jLabel1;
		private javax.swing.JLabel jLabel2;
		private javax.swing.JLabel jLabel3;
		private javax.swing.JPanel jPanel1;
		private javax.swing.JPanel jPanel2;
		private javax.swing.JPanel jPanel3;
		private javax.swing.JScrollPane jScrollPane1;
		private javax.swing.JTabbedPane jTabbedPane1;
		private javax.swing.JTextArea jTextArea1;
		private javax.swing.JCheckBox largeCheckBox;
		private javax.swing.JCheckBox mediumCheckBox;
		private javax.swing.JSlider mouseSlider;
		private javax.swing.JComboBox pathTypeComboBox;
		private javax.swing.JSlider sleepSlider;
		private javax.swing.JCheckBox smallCheckBox;
		private javax.swing.JCheckBox usePouchesCheckBox;
		// End of variables declaration

	}

}

class AStarGC {// Credits to Jacmob who credited DDM who credited some other guy

	private class Node {

		public int x, y;
		public Node parent;
		public double g, f;

		public Node(final int x, final int y) {
			this.x = x;
			this.y = y;
			g = f = 0;
		}

		public boolean isAt(final Node another) {
			return x == another.x && y == another.y;
		}

		public RSTile toRSTile(final int baseX, final int baseY) {
			return new RSTile(x + baseX, y + baseY);
		}

	}

	private int[][] blocks;

	public AStarGC() {

	}

	private Node cheapestNode(final ArrayList<Node> open) {
		Node c = null;
		for (final Node t : open) {
			if (c == null || t.f < c.f) {
				c = t;
			}
		}
		return c;
	}

	private double diagonalHeuristic(final Node current, final Node end) {
		final double dx = Math.abs(current.x - end.x);
		final double dy = Math.abs(current.y - end.y);
		final double diag = Math.min(dx, dy);
		final double straight = dx + dy;
		return Math.sqrt(2.0) * diag + straight - 2 * diag;
	}

	public RSTile[] findPath(final RSTile cur, final RSTile dest) {
		final int baseX = Bot.getClient().getBaseX(), baseY = Bot.getClient()
				.getBaseY();
		final int currX = cur.getX() - baseX, currY = cur.getY() - baseY;
		final int destX = dest.getX() - baseX, destY = dest.getY() - baseY;
		if (currX < 0 || currY < 0 || currX > 103 || currY > 103 || destX < 0
				|| destY < 0 || destX > 103 || destY > 103) {
			return null;
		}
		final ArrayList<Node> closed = new ArrayList<Node>(), open = new ArrayList<Node>();
		blocks = Bot.getClient().getRSGroundDataArray()[Bot.getClient()
				.getPlane()].getBlocks();
		Node current = new Node(currX, currY);
		final Node destination = new Node(destX, destY);
		open.add(current);
		while (open.size() > 0) {
			current = cheapestNode(open);
			closed.add(current);
			open.remove(open.indexOf(current));
			for (final Node n : getSurroundingWalkableNodes(current)) {
				if (!isIn(closed, n)) {
					if (!isIn(open, n)) {
						n.parent = current;
						n.g = current.g + getAdditionalCost(n, current);
						n.f = n.g + diagonalHeuristic(n, destination);
						open.add(n);
					} else {
						final Node old = getNode(open, n);
						if (current.g + getAdditionalCost(old, current) < old.g) {
							old.parent = current;
							old.g = current.g + getAdditionalCost(old, current);
							old.f = old.g + diagonalHeuristic(old, destination);
						}
					}
				}
			}
			if (isIn(closed, destination)) {
				return getPath(closed.get(closed.size() - 1), baseX, baseY);
			}
		}
		return null;
	}

	private double getAdditionalCost(final Node start, final Node end) {
		double cost = 1.0;
		if (!(start.x == end.y) || start.x == end.y) {
			cost = Math.sqrt(2.0);
		}
		return cost;
	}

	private Node getNode(final ArrayList<Node> nodes, final Node key) {
		for (final Node n : nodes) {
			if (n.isAt(key)) {
				return n;
			}
		}
		return null;
	}

	private RSTile[] getPath(final Node endNode, final int baseX,
			final int baseY) {
		final ArrayList<RSTile> reversePath = new ArrayList<RSTile>();
		Node p = endNode;
		while (p.parent != null) {
			reversePath.add(p.toRSTile(baseX, baseY));
			final int next = (int) (Math.random() * 4 + 5);
			for (int i = 0; i < next && p.parent != null; i++) {
				p = p.parent;
			}
		}
		final RSTile[] fixedPath = new RSTile[reversePath.size()];
		for (int i = 0; i < fixedPath.length; i++) {
			fixedPath[i] = reversePath.get(fixedPath.length - 1 - i);
		}
		return fixedPath;
	}

	private ArrayList<Node> getSurroundingWalkableNodes(final Node t) {
		final ArrayList<Node> tiles = new ArrayList<Node>();
		final int curX = t.x, curY = t.y;
		if (curX > 0 && curY < 103
				&& (blocks[curX - 1][curY + 1] & 0x1280138) == 0
				&& (blocks[curX - 1][curY] & 0x1280108) == 0
				&& (blocks[curX][curY + 1] & 0x1280120) == 0) {
			tiles.add(new Node(curX - 1, curY + 1));
		}
		if (curY < 103 && (blocks[curX][curY + 1] & 0x1280120) == 0) {
			tiles.add(new Node(curX, curY + 1));
		}
		if (curX > 0 && curY < 103
				&& (blocks[curX - 1][curY + 1] & 0x1280138) == 0
				&& (blocks[curX - 1][curY] & 0x1280108) == 0
				&& (blocks[curX][curY + 1] & 0x1280120) == 0) {
			tiles.add(new Node(curX + 1, curY + 1));
		}
		if (curX > 0 && (blocks[curX - 1][curY] & 0x1280108) == 0) {
			tiles.add(new Node(curX - 1, curY));
		}
		if (curX < 103 && (blocks[curX + 1][curY] & 0x1280180) == 0) {
			tiles.add(new Node(curX + 1, curY));
		}
		if (curX > 0 && curY > 0
				&& (blocks[curX - 1][curY - 1] & 0x128010e) == 0
				&& (blocks[curX - 1][curY] & 0x1280108) == 0
				&& (blocks[curX][curY - 1] & 0x1280102) == 0) {
			tiles.add(new Node(curX - 1, curY - 1));
		}
		if (curY > 0 && (blocks[curX][curY - 1] & 0x1280102) == 0) {
			tiles.add(new Node(curX, curY - 1));
		}
		if (curX < 103 && curY > 0
				&& (blocks[curX + 1][curY - 1] & 0x1280183) == 0
				&& (blocks[curX + 1][curY] & 0x1280180) == 0
				&& (blocks[curX][curY - 1] & 0x1280102) == 0) {
			tiles.add(new Node(curX + 1, curY - 1));
		}
		return tiles;
	}

	private boolean isIn(final ArrayList<Node> nodes, final Node key) {
		return getNode(nodes, key) != null;
	}

}
